﻿#region license
//------------------------------------------------------------------------------
// <copyright company="Ascertaint.org">
//     Copyright (c) Ascertaint.org.  All rights reserved.
// </copyright> 
//
// Authors: Ming Tsai (ming@ascertaint.org)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//------------------------------------------------------------------------------
#endregion

using System;
using System.Text.RegularExpressions;
using System.Text;
using System.Web;

namespace Ums.CellPhoneInfo {
    /// <summary>
    /// CellPhoneParser is the main worker that do the parsing.
    /// </summary>
    public abstract class CellPhoneParser {
        /// <summary>
        /// Parses the given number into CellPhoneNumber object.
        /// </summary>
        /// <remarks>if country cannot be determined, will use DefaultCellPhoneParser as default.</remarks>
        /// <param name="numToParse"></param>
        /// <returns></returns>
        public static CellPhoneNumber Parse(string numToParse) {
            CellPhoneNumber result = new CellPhoneNumber();
            string iso = DetermineCountry(numToParse);

            //stript off international calling prefix
            //
            //string stationCountry = "tw";
            //string Internal_calling_prefix = "002,005,006,007,009,019";            
            string calling_prefix_pattern_tw = "^002|^005|^006|^007|^009|^019";
            numToParse = Regex.Replace(numToParse, calling_prefix_pattern_tw, "");

            switch (iso) {
                case "tw": {
                        TaiwanCellPhoneParser p = new TaiwanCellPhoneParser();
                        result = p.ParseExact(numToParse);
                        break;
                    }
                case "cn": {
                        ChinaCellPhoneParser p = new ChinaCellPhoneParser();
                        result = p.ParseExact(numToParse);
                        break;
                    }
                case "us" : {
                        USACellPhoneParser p = new USACellPhoneParser();
                        result = p.ParseExact(numToParse);
                        break;                    
                }
                case "intl": {
                        DefaultCellPhoneParser p = new DefaultCellPhoneParser();
                        result = p.ParseExact(numToParse);
                        break;
                    }
            }
            return result;
        }

        /// <summary>
        /// Returns true if the given number is valid mobile phone number.
        /// </summary>
        /// <param name="numToParse"></param>
        /// <returns></returns>
        public static bool IsValidNumber(string numToParse) {
            bool result = false;
            string iso = DetermineCountry(numToParse);
            switch (iso) {
                case "tw": {
                        TaiwanCellPhoneParser p = new TaiwanCellPhoneParser();
                        result = p.IsValid(numToParse);
                        break;
                    }
                case "cn": {
                        ChinaCellPhoneParser p = new ChinaCellPhoneParser();
                        result = p.IsValid(numToParse);
                        break;
                    }
                case "usa": {
                        USACellPhoneParser p = new USACellPhoneParser();
                        result = p.IsValid(numToParse);
                        break;
                    }
                case "intl": {
                        DefaultCellPhoneParser p = new DefaultCellPhoneParser();
                        result = p.IsValid(numToParse);
                        break;
                    }
            }
            return result;
        }

        /// <summary>
        /// Determines country ISO 3361-1 code from the given mobile phone number. Returns "intl" if not found.
        /// </summary>
        /// <param name="numToParse"></param>
        /// <returns></returns>
        public static string DetermineCountry(string numToParse) {
            string iso = "";
            
            string num = HttpUtility.UrlDecode(numToParse);
            num = StriptOffNonNumeric(numToParse);

            //*************************************
            // we will need to read off user or UmsSettings to get the station country
            // in order to determine which is "international calling prefix
            // hard code to taiwan for now
            // ming 8/24/2007
            //*************************************

            //stript off international calling prefix
            //
            //string stationCountry = "tw";
            //string Internal_calling_prefix = "002,005,006,007,009,019";            
            string calling_prefix_pattern_tw = "^002|^005|^006|^007|^009|^019";
            num = Regex.Replace(num, calling_prefix_pattern_tw, "");
                        
            //determine country
            //
            if (Regex.IsMatch(num, TaiwanCellPhoneParser.PhonePattern)) {
                iso = "tw";
                return iso;                
            }
            else if (Regex.IsMatch(num, ChinaCellPhoneParser.PhonePattern)) {
                iso = "cn";
                return iso;
            }
            else if (Regex.IsMatch(num, USACellPhoneParser.PhonePattern) && num.Length == 10) {
                iso = "us";
                return iso;
            }
            else {
                iso = "intl";
                return iso;
            }
            //return iso;
        }

        /// <summary>
        /// Removes all non-numeric charactors.
        /// </summary>
        /// <returns></returns>
        public static string StriptOffNonNumeric(string num) {
            string result = "";
            char[] ar = num.ToCharArray();
            for (int i = 0; i < ar.Length; i++) {
                if (Char.IsDigit(ar[i])) {
                    result = result + ar[i];
                }
            }
            return result;
        }

        /// <summary>
        /// Returns true if numTocheck contains non-numeric charactor
        /// </summary>
        /// <param name="numTocheck"></param>
        /// <returns></returns>
        public static bool ContainNonNumeric(string numTocheck) {
            char[] ar = numTocheck.ToCharArray();
            for (int i = 0; i < ar.Length; i++) {
                if (!Char.IsDigit(ar[i])) {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Returns true if the given number is a valid mobile number.
        /// </summary>
        /// <param name="numToParse"></param>
        /// <returns></returns>
        protected abstract bool IsValid(string numToParse);

        /// <summary>
        /// Parses the given number into CellPhoneNumber.
        /// </summary>
        /// <remarks></remarks>
        /// <param name="numToParse"></param>
        /// <returns></returns>
        protected abstract CellPhoneNumber ParseExact(string numToParse);
    }
}